const webpack = require('webpack');
const { Configuration, DllReferencePlugin } = webpack
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MyPlugin = require('./MyPlugin');
// const MiniCssExtraPlugin = require('mini-css-extra-plugin');
// const OptimizeCssAssertWebpackPlugin = require('optimize-css-assert-webpack-plugin');

/**
 * @type {Configuration}
 */
const config = {
  // entry: './src/main.js',
  entry: {
    index: './src/main.js',
    other: './src/components/dynamicImport/render.js',
  },
  mode: 'none', // 和development的打包产物有区别
  output: {
    filename: '[name]-[contenthash:8].bundle.js', // hash,chunkhash,contenthash分别指打包,chunk,文件内容的hash.:number 指定hash的位数
    path: path.resolve(__dirname, 'dist'),
  },
  // eval: 是否使用eval包裹每个模块
  // cheap: source map 是否包含行信息
  // module: 是否包含loader处理之前的source map
  // inline: source map在data url中
  // hidden: 是否隐藏source map(转换后的代码最后不添加sourceMappingURL)
  // nosources: 是否隐藏source map中的sourcesContent,保护源代码
  devtool: 'source-map', // 是否生成sourcemap
  plugins: [
    new DllReferencePlugin({
      manifest: require('./dll/vue.manifest.json'),
    }),
    new CleanWebpackPlugin(), // 每次build前清理dist目录
    new HtmlWebpackPlugin({
      title: 'test title',
      meta: {
        viewport: 'width=device-width, initial-scale=1.0'
      },
      template: './src/index.html',
      filename: 'index.html',
      chunks: ['index'], // 指定引入的chunk,多入口时指定引入的chunk
    }),
    new HtmlWebpackPlugin({
      title: 'render title',
      meta: {
        viewport: 'width=device-width, initial-scale=1.0'
      },
      template: './src/index.html',
      filename: 'render.html',
      chunks: ['other'], // 指定引入的chunk,多入口时指定引入的chunk
    }),
    new MyPlugin(), // 自定义plugin
    new webpack.HotModuleReplacementPlugin(), // 热替换插件
    new webpack.DefinePlugin({ // 实现原理是将编译后的文件进行字符替换,因此在js环境下注意字符串应如"'string''"
      'process.env': {
        NODE_ENV: JSON.stringify('development')
      },
      'API_BASE_URL': JSON.stringify('http://localhost:3000')
    }),
    // new MiniCssExtraPlugin(), // 将css提取到单独文件,使用后需要MiniCssExtraPlugin.loader替换style-loader
  ],
  module: {
    rules: [{
      test: /\.md$/, // 自定义loader
      use: './markdown-loader.js'
    },
      // {
      //   test: /\.js$/,
      //   use: {
      //     loader: 'babel-loader',
      //     options: {
      //       presets: ['@babel/preset-env', { modules: 'commonjs' }], // 强制开启esm转换为commonjs后,tree-shaking就失效了
      //     }
      //   }
      // }
    ],
  },
  devServer: {
    contentBase: './public', // 本地服务能访问public下的静态资源
    proxy: { // 代理服务,将本地接口转发到目标服务上
      '/api': { // 本地以`/api`开头的服务
        target: 'https://api.github.com', // 目标服务
        // 当前结果 http://localhost:8080/api/users -> https://api.github.com/api/users 
        pathRewrite: {
          '^/api': '', // 将目标服务上的/api开头的路径替换
        },
        // 当前结果 http://localhost:8080/api/users -> https://api.github.com/users 
        changeOrigin: true, // 是否改变请求源 修改请求的origin头为目标服务,否则目标服务可能会拒绝
      }
    },
    hot: true, // 开启热替换
    // hotOnly: true, // 报错后,不刷新页面,方便调试
  },
  optimization: {
    usedExports: true, // 只打包用到的export  生产模式自动开启
    minimize: true, // 压缩代码,生产模式自动开启
    concatenateModules: true, // 尽可能合并模块,生产模式自动开启
    sideEffects: true, // 标记哪些模块没有副作用(模块间不会相互影响:例外修改原型,css文件),tree-shaking依赖
    splitChunks: { // 代码分割
      chunks: 'all', // 将公共的模块单出来,异步加载的模块也单出来
    },
    minimizer: [
      // new OptimizeCssAssertWebpackPlugin(), // 压缩css
    ]
  }
}

module.exports = config

// 不同环境配置大型项目通常是通过文件区分的